<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- 普通继承 -->
    <!-- <script>
        class Shape {
            constructor(name) {
                this.name = name
            }

            draw() {
                console.log(`draw ${this.name}`)
            }
        }

        class ShapeColor extends Shape {
            constructor(name) {
                super(name)
            }

            setColor(color) {
                console.log(`color the ${this.name} ${color}`)
            }
        }

        const circle = new ShapeColor('圆形')
        circle.setColor('blue')
        circle.draw()

    </script> -->

    <!-- 装饰器模式 -->
    <script>
        // @SayhelloDecorator
        class Shape {
            constructor(name) {
                this.name = name
            }

            draw() {
                console.log(`绘制${this.name}`)
            }
        }

        /* 
        颜色装饰器 
        加强入参shape的draw方法
        */
        class ColorDecorator {
            constructor(shape) {
                this.shape = shape
            }

            setColor() {
                console.log(`${this.shape.name}设置颜色`)
            }

            /* 加强入参shape的绘制方法 */
            draw() {
                // 先设置颜色再绘制
                this.setColor()

                // shape本来的绘制方法
                this.shape.draw()
            }
        }

        /* 
        日志装饰器
        在draw方法的前后生成特殊日志

        =======================
        方法的具体执行
        =======================
        */
        class LogDecorator {
            constructor(target) {
                this.target = target
            }
            draw() {
                console.log("=======================");
                this.target.draw()
                console.log("=======================");
            }
        }

        /* 给class添加sayHello方法 */
        function SayhelloDecorator(targetClass) {
            // Shapte.prototype.sayHello = function () {
            //     console.log("hello");
            // }

            Object.assign(
                targetClass.prototype,
                {
                    sayHello: function () {
                        console.log("hello");
                    }
                }
            )
        }

        let circle = new Shape('圆圈')
        circle.draw()
        console.log("-----");

        let xCircle = new ColorDecorator(circle)
        xCircle.draw()
        console.log("-----");

        let xxCircle = new LogDecorator(xCircle)
        xxCircle.draw()

        SayhelloDecorator(Shape)
        const shCircle = new Shape('圆圈')
        shCircle.sayHello()

    </script>

    <!-- ES7装饰器（实验性质） -->
    <!-- 简单示例 -->
    <!-- <script>
        @dec
        class Shape { }

        function dec(target) {
            target.isShape = true
        }

        console.log(Shape.isShape)
    </script> -->

    <!-- 参数传递 -->
    <!-- <script>
        @HasWife(false)
        class Shape {}

        function HasWife(hasWife) {
            return function (target) {
                target.hasWife = hasWife
            }
        }

        console.log(Shape.hasWife)
    </script> -->

    <!-- mixin -->
    <!-- <script>
        function mixin(...attrs) {
            return function (target) {
                Object.assign(target.prototype, ...attrs)
            }
        }

        const attrs = {
            setColor() {
                console.log('set color')
            }
            getColor(){
                return this.color
            }
        }

        @mixin(attrs)
        class Shape { }

        let shape = new Shape()
        shape.setColor()
    </script> -->

    <!-- 装饰方法 -->
    <!-- <script>
        class Shape {
            @log
            setColor(color) {
                return color
            }
        }

        function log(target, name, descriptor) {
            var oldValue = descriptor.value

            descriptor.value = function () {
                console.log(`Calling ${name} with `, arguments)
                return oldValue.apply(this, arguments)
            }

            return descriptor
        }

        const shape = new Shape()
        const color = shape.setColor('red')
        console.log('color', color)
    </script> -->

</body>

</html>